home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
ctut.arc
/
LESSON6
< prev
next >
Wrap
Text File
|
1986-02-07
|
24KB
|
668 lines
.NT
A NOTE ABOUT THE LESSONS in C
.b4-24
.R5C4
These were written while the author was ~Ilearning~N the language and since
.R6C4
they are ~Ifree~N ( to copy and/or distribute ) there is a money-back
.R7C4
guarantee on the accuracy of each and every statement in the lessons (!)
.R9C4
The ~Idisplay~N program was written ( in C ) in order to provide a vehicle
.R10C4
for displaying the lessons.
.R12C5
.B
P.J.Ponzo
.B
Dept. of Applied Math
.B
Univ. of Waterloo
.B
Ontario N2L 3G1
.K16,30
PonzoTUTOR
.WNT
POINTERS and ARRAYS
.R4C1
Recall that, when we refer to ~b~I&x~N, ~IC~N will interpret this as the
~Iaddress~N in memory of the variable ~b~Ix~N. Here ~b~I&x~N is a ~w~Rpointer~N.
If we set ~b~Iy=&x~N, in our program, then ~b~Iy~N ~w~Rpoints~N to the
variable ~b~Ix~N ( ~b~Iy~N is now an address, in memory ).
.b9-11
.R10C17
~V HOW DO WE DECLARE A POINTER VARIABLE ? ~N
.W
.R10C17
~V patience ~N
In addition to the ~b~I&~N ~Ioperator~N (which returns the ~Iaddress~N of
the variable which follows it), there is the C ~Ioperator~N ~b~I*~N.
If ~b~Iy~N points to ~b~Iint x~N, then ~b~I*y~N is the ~Icontents of memory~N
~Ilocation y~N. When a program refers to ~b~I*y~N, the C compiler will go
to the address given by the ~w~Rpointer~N ~b~Iy~N, extract the ~b~Iint~Neger
it finds there, and use this ~b~Iint~Neger in place of ~b~I*y~N.
This poses a problem.....
.K19,60
a problem?
.WN
How is the compiler to know whether the contents of the address ~b~Iy~N,
(which we refer to as ~b~I*y~N, in our program) is an ~b~Iint~Neger or a
~b~Ifloat~Ning point number or a ~b~Ichar~Nacter variable ???
Since an ~b~Iint~Neger occupies ~I2~N bytes ( usually ..depending upon the
computer you are using) and a single ~b~Ichar~Nacter variable occupies
just ~I1~N byte and a ~b~Ifloat~N occupies ~I4~N bytes ...etc. etc...then
it's clearly important that the compiler KNOW that ~b~Iy~N is pointing to
an ~b~Iint~N or a ~b~Ichar~N or a ~b~Ifloat~N ...etc.
~ISO ... we must declare the type of variable that ~b~Iy~N points to !~N
To do this we declare ~Ithe contents of y~N, namely ~b~I*y~N !!
.K19,60
example?
.WN
1 ~b~Imain() { ~N
2 ~b~I int *y; ~N
3 ~b~I int x=123; /* x=integer 123 */~N
4 ~b~I y=&x; /* y=address of x */~N
5 ~b~I printf("The value of x is %d",*y); ~N
6 ~b~I} ~N
This program will (correctly) print: ~r~IThe value of x is 123~N
.K19,60
int *y;
Note that, in line 4, ~b~Iy~N is made a ~w~Rpointer~N, pointing to ~b~Ix~N
and ~b~Ix~N is an ~b~Iint~N .... ~ISO~N ... in line 2 we declare our
~w~Rpointer~N ~b~Iy~N as: ~b~I int *y ~N since it points to an ~b~Iint~N.
.K19,60
all clear?
.WN
~V ~N
~V REMEMBER!! IF sam IS A POINTER TO SOME VARIABLE, ~N
~V THEN BE SURE TO DECLARE *sam AS THE SAME ~N
~V TYPE AS THE VARIABLE TO WHICH sam POINTS! ~N
~V ~N
.b1-7
.K19,32
mamma mia!
.R10C1
If ~b~Ix~N is an ~Iint~N and ~b~Iy=&x~N then declare : ~b~Iint *y~N
If ~b~Ix~N is a ~Ichar~N and ~b~Iy=&x~N then declare : ~b~Ichar *y~N
If ~b~Ix~N is a ~Ifloat~N and ~b~Iy=&x~N then declare : ~b~Ifloat *y~N
.WNT
VARIABLES and their HOMES in MEMORY
We've mentioned that the ~b~Ichar c~N occupies ~I1~N byte of memory, and
that ~b~Iint i~N occupies ~I2~N bytes and ~b~Ifloat f~N occupies ~I4~N bytes.
Suppose ~b~Ipc=&c~N is a ~w~Rpointer~N to ~b~Ic~N, and ~b~Ipi=&i~N and ~b~Ipf=&f~N.
~V WHERE DOES pc+1 POINT TO ? ~N
and ~V WHERE DOES pi+1 POINT TO ? ~N
and ~V WHERE DOES pf+1 POINT TO ? ~N
.K16,32
I give up!
.WN
.B
.B
.B
.B
.B
.B
.B
.B
.B
.B
.B
.B
.R4C2
pc-2 pc-1 pc pc+1 pc+2 pc+3 pc+4 pc+5 pc+6 pc+7 pc+8
If the boxes are each ~I1~N byte of memory, and ~b~Ipc~N points to one
such byte, then the scheme shown above indicates where ~b~Ipc-2~N, etc.
point to.
The fact that ~b~Ipc~N is a ~w~Rpointer~N to a ~b~Ichar~N (because we would
(should?) have declared it with ~b~Ichar *pc~N) and because a ~b~Ichar~N
only occupies ~I1~N byte, then ~IC~N is smart enough to know that ~b~Ipc-2~N
is the address of the memory location 2 bytes below ~b~Ipc~N.
.K16,32
try int!
.WN
.B
.B
.B
.B
.B
.B
.B
.B
.B
.B
.B
.B
.R4C2
pi-1 pi pi+1 pi+2 pi+3 pi+4
Now ~b~Ipi~N points to a (~I2~N byte) ~b~Iint~N, so ~IC~N (whatta guy!)
arranges that ~b~Ipi-1~N points ~I2~N bytes earlier than ~b~Ipi~N ...that
way it will point to the IMMEDIATELY PRECEDING ~b~Iint~N.
(...of course, who knows if there IS an ~b~Iint~N stored at ~b~Ipc-1~N ?!)
.W
.K16,32
TRY FLOAT!
.WN
.B
.B
.B
.B
.B
.B
.B
.B
.B
.B
.B
.B
.R4C2
pf pf+1 pf+2
You guessed it! ~b~Ipf+1~N will point to the VERY NEXT ~b~Ifloat~N,
~I4~N bytes past where ~b~Ipf~N points.
(...ain't ~Iaddress arithmetic~N wonderful ? )
NOTE:If we have ~b~Imain() { ~N
~b~I float f, *pf; ~N
~b~I f=12.3; ~N
~b~I pf=&f; ~N
then what IS ~I4~N bytes past the address of ~b~If~N ???
There is one circumstance where we WILL know "what comes after".
.K19,60
GUESS!
.WNT
hip hip ARRAYS
.R4C1
You may recall, from an earlier lesson, that we defined a string by
declaring it to be an ARRAY of (single) ~b~Ichar~Nacters.
We'll reproduce it here:
~b~Ichar x[10];~N defines an ~IARRAY~N of ~b~I10~N elements.
~b~Ix[0]='A';~N the first element is the character ~b~IA~N.
~b~Ix[1]='b';~N the second element is the character ~b~Ib~N.
~b~Ix[2]='{';~N the third element is the character ~b~I{~N.
~b~Ix[3]='\0';~N the last element is the 'number' ~I0~N!!!!
~b~Iprintf("the string is %s",x);~N print the string, up to the ~I0~N.
...and the printout would be: ~r~Ithe string is Ab{~N
.K19,60
remember?
.WN
~b~Imain() { ~N
~b~I char x[10], *px; ~N
~b~I x[0]='A'; ~N
~b~I x[1]='b'; ~N
~b~I x[2]='{'; ~N
~b~I x[3]='\0'; ~N
~b~I printf("the string is %s",x); ~N
NOW, if we define ~b~Ipx=&x[0]~N, a ~w~Rpointer~N to the first element in
the ARRAY ~b~Ix[]~N, then:
.W
.Q
What character does px+2 point to ?
{
~b~Iprintf("%c%c%c",*px,*(px+1),*(px+2));~N
.Q
What will the above print?
Ab{
~b~Iprintf("%c",*px);~N would print the contents of memory location
~b~Ipx~N, namely ~r~IA~N, and ~b~Iprintf("%c",*(px+1));~N prints ~r~Ib~N,
and ~b~Iprintf("%c",*(px+2));~N prints ~r~I{~N, and ALL THREE GIVE: ~r~IAb{~N.
( ...a-a-a-h, C is ~Iso~N clever ...)
.K2,60
whatta gal
.WN
1 ~b~I char x[4]; ~N
2 ~b~I x[0]='A'; ~N
3 ~b~I x[1]='b'; ~N
4 ~b~I x[2]='{'; ~N
5 ~b~I x[3]='\0'; ~N
In this program excerpt, we defined some elements of the ARRAY ~b~Ix[10]~N
by saying ( laboriously ):~b~Ix[0]='A'; x[1]='b'; x[2]='{'; x[3]='\0';~N
For a ~b~Ichar~N ARRAY we can also say:
~b~Ichar x[4]={ 'A','b','{','\0' };~N
making Lines 2-5 unnecessary.
For an ~b~Iint~N ARRAY we can say:
~b~Iint x[3]={11,12,13};~N
Under certain conditions, all ARRAYS may be ~Iinitialized~N (defined as they
are declared). We'll talk about this later ...
.K10,60
curly {
.WNT
More POINTERS and ARRAYS
.R4C1
When we define an ARRAY, say: ~b~I int s[10];~N then each of ~b~Is[0]~N,
~b~Is[1]~N, etc are (~I2~N byte) ~b~Iint~Negers.
~I...and here's something special:~N
.b6-8
.R10C1
~b~Is~N, all by itself, is a ~w~Rpointer~N to ~b~Is[0]~N
.b9-11
.K19,60
WHAT!
.W
.R12C1
1 ~b~Imain() { ~N
2 ~b~I int s[3]; /* define integer array */ ~N
3 ~b~I s[0]=11; s[1]=12; s[2]=13; /* define members of s[] */ ~N
4 ~b~I printf("%d",s[0]); /* print first integer */ ~N
5 ~b~I printf("\n%d",*s); /* print what s points to*/ ~N
6 ~b~I} ~N
Line 4 will print ~r~I11~N and line 5 will print ~r~I11~N !!!
..proving that s[0] and *s are the same, right?
..so ~Is is a pointer to s[0]~N, right?
.K19,60
RIGHT!
.W
Of course it would have been easier to say:
2 ~b~Iint s[3]={11,12,13};~N and omit Line 3!
.WN
NOW, since an ARRAY (~Iany~N ARRAY, whether ~b~Iint~Ns or ~b~Ichar~Ns or ~b~Ifloats~N)
~Vhas its name as a pointer~N (..think about that! ), then not only will ~b~Is[2]~N
give the 3rd element in the ARRAY, ~Ibut so will *(s+2) give the 3rd element!~N
Here's a program you've seen in an earlier lesson (on STRINGS):
1 ~b~Imain() { ~N
2 ~b~I char s; /* declare a char */ ~N
3 ~b~I s="I am a string"; /* make it a string */ ~N
4 ~b~I printf("%s",s); /* print the string */ ~N
5 ~b~I printf("\n%s",s+2); /* what ????? */ ~N
6 ~b~I} ~N
Line 2 declares ~b~Is~N to be of type ~b~Ichar~N.
Line 3 defines ~b~Is~N to be a string ( double quotes, remember?).
Line 4 prints the ~b~I%s~Ntring, giving ~r~II am a string~N
Line 5 prints .... ~r~Iam a string~N
.W
Here, just as for an ARRAY, ~b~Is~N is a ~w~Rpointer~N to the string
~b~I"I am a string"~N. In fact, ~b~Is~N points to the first element: ~b~II~N.
HENCE, ~b~Is+2~N points to the ~I3rd element~N (~b~Ia~N) and ~b~Iprintf()~N will
(upon receipt of a ~b~I%s~Ntring address) print everything from that
address up to the special terminating ~I'\0'~N ( ...remember him?).
.WK7,32
magnifico!
.WN
~ITHE NAME OF A STRING VARIABLE IS A POINTER TO THE FIRST ELEMENT IN THE STRING!
~ITHE NAME OF AN ARRAY VARIABLE IS A POINTER TO THE FIRST ELEMENT IN THE ARRAY !
.b5-11
~I
.K16,32
REMEMBER!
.WR3C1
...and ~r~Ipointer~N arithmetic is wonderful...
.b2-4
.WNT
Be kind to your compiler
.R4C1
Now, if we declare ~b~Ichar a[30];~N the C-compiler knows that ~b~Ia~N refers
to a collection of ~I30~N ~b~Ichar~Ns ...and it knows this even before we define
the elements ~b~Ia[0]~N, ~b~Ia[1]~N, etc.
BUT, if we declare ~b~Ichar s;~N, how is the compiler to know whether ~b~Is~N
if a single ~b~Ichar~N or a string of ~b~Ichar~Ns. If, subsequently, we say
~b~Is="I am a string"~N then ~b~Is~N IS a string ..but if we say ~b~Is='A'~N
then ~b~Is~N is just one ~b~Ichar~N ...but should we REALLY make the compiler
figure this out? After all, the compiler would reserve a single byte in
memory for just one ~b~Ichar~N but may have to reserve dozens of bytes for
a string of ~b~Ichars~N!
~VMORAL~N: DECLARE A SINGLE CHARACTER AS ~b~Ichar s;~N
DECLARE A STRING OF CHARS AS ~b~Ichar *s;~N
.b15-18
Since we (and the compiler) know that the name of a string is a ~w~Rpointer~N
then the declaration ~b~Ichar *s;~N (followed perhaps by ~b~Is="I'm a string"~N)
just anticipates the subsequent use of ~b~Is~N as the name of a string (as
opposed to a single character).
.WNR3
~b~I ~N
~b~I char s; ~N
~b~I s="I am a string"; ~N
~b~I printf("%s",s); ~N
~b~I ~N
Although we have used the above format in earlier lessons .....
.B
IT MAY NOT COMPILE!
.R14C1
...and if it does
.B
IT MAY NOT WORK!
.WR4C40
~b~I char *s; ~N
.R21B
If we use ~b~Ichar *s~N then ALL compilers will accept it.
.WN
We have:
If ~b~Is~N is the name of a string (defined with ~Idouble quotes~N) then
~b~Is~N ~b~Is+1~N ~b~Is+2~N etc ~w~Rpoint~N to the ~I1st~N ~I2nd~N ~I3rd~N etc.
members of the string.
.b2-6
.R8C1
If ~b~Is~N is the name of an ARRAY (defined with ~b~Is[0]=...~N etc.) then
~b~Is~N ~b~Is+1~N ~b~Is+2~N etc ~w~Rpoint~N to the ~I1st~N ~I2nd~N ~I3rd~N etc.
members of the ARRAY.
.b7-11
.K17,60
hmmmmmm...
.WN
Now, don't think that strings and ARRAYs are the same ...after all a string
is only an ~IARRAY of (single) ~bchar~N~I variables~N whereas we can also have
ARRAYs of ~b~Iint~Ns or ~b~Ifloats~N or other interesting ~Idata types~N.
.W
Further, the name of a string pointer is a VARIABLE:
1 ~b~Imain() { ~N
2 ~b~I char *x, *y, *z; /* 3 pointers to strings */ ~N
3 ~b~I x="ABC"; /* x points to string ABC */ ~N
4 ~b~I y="DEF"; /* y points to string DEF */ ~N
5 ~b~I z=x; /* z points to string ABC */ ~N
6 ~b~I printf(" The x-string is %s",z); ~N
7 ~b~I z=y; /* z points to string DEF */ ~N
8 ~b~I printf(" The y-string is %s",z); ~N
9 ~b~I ~N
In line 5 we make ~b~Iz~N point to the same thing that ~b~Ix~N points to
...and line 6 prints: ~r~I The x-string is ABC~N
In line 7 we make ~b~Iz~N point to the same thing that ~b~Iy~N points to
...and line 8 prints: ~r~I The y-string is DEF~N
.W
BUT, we could also say: ~b~Ix=y;~N and make ~b~Ix~N point to the y-string!
.WNT
STRINGS and 1-dimensional CHAR ARRAYS
.R4C1
Suppose we may declare strings ~b~Ic~N and ~b~Ix~N by using:
1 ~b~Ichar c[9]={'c','-','s','t','r','i','n','g','\0'}; ~N
2 ~b~Ichar *x="x-string"; ~N
In the first instance, ~b~Ic~N is a ~r~Ipointer~N to an ARRAY of ~b~Ichar~Nacter
variables (8 ~b~Ichar~Ns: ~Ic-string~N , plus the terminating '\0').
In the second instance, ~b~Ix~N is ~Ialso~N a ~r~Ipointer~N, but now it's a
~r~Ipointer~N to a ~Istring~N: ~b~Ix-string~N with (again) the terminating
'\0' (which ~IC~N looks after appending).
SO WHAT'S THE DIFFERENCE BETWEEN char c[] and char *x ???
.K19,60
I give up
.WN
1 ~b~Ichar c[9]={'c','-','s','t','r','i','n','g','\0'}; ~N
2 ~b~Ichar *x="x-string"; ~N
In the first case, ~b~Ic~N is a ~ICONSTANT POINTER~N to the first element of
the ARRAY ...and ~Icannot be changed~N.
In the second case, ~b~Ix~N is a ~IVARIABLE POINTER~N to the first element of
the string ...and ~ICAN~N be changed!
.K19,32
WHAT!
.WN
1 ~b~Ichar c[9]={'c','-','s','t','r','i','n','g','\0'}; ~N
2 ~b~Ichar *x="x-string"; ~N
3 ~b~Iprintf(" %s %s ",c,x); /* print %strings c and x */ ~N
4 ~b~Ix=c; /* make x point to c */ ~N
5 ~b~Iprintf(" %s %s ",c,x); /* print %strings c and x */ ~N
Just to show that it is ~b~Ix~N (and ~INOT~N ~b~Ic~N) which is a VARIABLE,
we declare/define them both in Lines 1 and 2.
Then print them both in Line 3. We would get:
~r~I c-string x-string~N
Then we ~Ichange x~N, in Line 4, so it points to the same thing as ~b~Ic~N does,
then print them both again, in Line 5. We'd get:
~r~I c-string c-string~N
You must not try: ~b~Ic=x;~N because it won't compile!
ARRAY names point (ALWAYS and FOREVER) to the first element of the ARRAY!
.b19-21
.WNT
more and more ARRAYS
.R4C1
In addition to an ARRAY such as ~b~Ix[10]~N (with 10 elements,
which may be char,int,float,etc.),here's a ~Idouble ARRAY~N:
~b~Ifloat x[5][7];~N This declares an ARRAY of 5*7=~I35~N
floating point numbers. We may define any or all
of them (for example we may write ~b~Ix[2][1]=1.5~N).
We think of this ARRAY as being arranged like so:
.R12C1
x[0][0] x[0][1] x[0][2] x[0][3] x[0][4] x[0][5] x[0][6]
x[1][0] x[1][1] x[1][2] x[1][3] x[1][4] x[1][5] x[1][6]
x[2][0] x[2][1] x[2][2] x[2][3] x[2][4] x[2][5] x[2][6]
x[3][0] x[3][1] x[3][2] x[3][3] x[3][4] x[3][5] x[3][6]
x[4][0] x[4][1] x[4][2] x[4][3] x[4][4] x[4][5] x[4][6]
.b11-17
.K4,66
x[i][j][k]
.WR4C1
.R4C1
Now, if we define ~b~Ix[2][1]=1.5~N, the number 1.5 goes here!
.sR14C20
~Fx[2][1]~N
.r
...and, as you might expect, we can have ~I3-dimensional~N ARRAYS, etc.
.rK4,66
x[i][j][k]
.WN
~V x[0][0] x[0][1] x[0][2] x[0][3] x[0][4] x[0][5] x[0][6] ~N
~V x[1][0] x[1][1] x[1][2] x[1][3] x[1][4] x[1][5] x[1][6] ~N
~V x[2][0] x[2][1] x[2][2] x[2][3] x[2][4] x[2][5] x[2][6] ~N
~V x[3][0] x[3][1] x[3][2] x[3][3] x[3][4] x[3][5] x[3][6] ~N
~V x[4][0] x[4][1] x[4][2] x[4][3] x[4][4] x[4][5] x[4][6] ~N
When we declare a multi-dimensional ARRAY, as in ~b~Ifloat x[5][~F7~N~b~I]~N, the
C-compiler knows that each element occupies ~I4 bytes~N in memory (because
it's an ARRAY of ~b~Ifloat~Ns) ..hence it knows not only how much memory
is needed but where each element is. Starting at the ~Iaddress~N of the first
element, ~b~I&x[0][0]~N, we find the ~Iaddress~N of ~b~Ix[~F2~N~b~I][~F1~N~b~I]~N by moving
~F~I7~N*~F~I2~N+~F~I1~N=15 elements along the ARRAY ...and at 4-bytes-per-element
that means moving 4*15=60 bytes through memory.
Notice how important the number of ~Icolumns~N is to the C-compiler (in the
declaration ~b~Ifloat x[5][7]~N
Without this dimension the compiler wouldn't know how to get to ~b~Ix[2][1]~N!
In fact, ~IYOU MAY LEAVE OUT THE NUMBER OF ROWS IN DECLARING THIS ARRAY!~N
(and use ~b~Ifloat x[][7]~N instead!)
.WR6C1s
.r
A 2-dimensional ARRAY is treated (by ~IC~N) as a 1-dimensional ARRAY each
of whose elements is a 1-dimensional ARRAY.
The ARRAY ~b~Ifloat x[5][7]~N consists of ~I5~N 1-dimensional ARRAYS, called
(in C-speak), ~b~Ix[0]~N, ~b~Ix[1]~N, ~b~Ix[2]~N, etc. and each of these
1-dimensional ARRAYS has ~I7~N elements.
Since (for example) the element 3 of an ARRAY ~b~Isam~N is called ~b~Isam[3]~N
then element 3 of the (1-dimensional) ARRAY ~b~Ix[2]~N is called ~b~Ix[2][3]~N
... which explains the C-notation for 2-dimensional ARRAYS,
x[i][j], rather than (the more usual) x[i,j].
In fact, you may refer to ~b~Ix[2][3]~N as ~b~I(x[2])[3]~N ... meaning
element 3 of the (1-dimensional) ARRAY x[2] (actually the 4th element
since the first is element 0 !!!@#$*).
.WR3C1
~V x[2][0] x[2][1] x[2][2] ~Fx[2][3]~N~V x[2][4] x[2][5] x[2][6] ~N
.WN
If ~IC~N regards ~b~Ix[5][7]~N as consisting of ~I5~N 1-dimensional ARRAYS
~b~Ix[0]~N, ~b~Ix[1]~N, ~b~Ix[2]~N, ~b~Ix[3]~N, and ~b~Ix[4]~N then what
does (for example) ~b~Ix[2]~N refer to ? What happens if we printf() ~b~Ix[2]~N?
Is ~b~Ix[2]~N just a notation or does it refer to one of the ~I5*7=35~N members
of ~b~Ix[5][7]~N ?
.b2-8
.K10,32
I give up!
.WN
Actually, ~IC~N is very clever. ~b~Ix[2]~N (all by itself) is a ~r~Ipointer~N to the
first element in the 1-dimensional ARRAY ~b~Ix[2]~N, namely ~b~Ix[2][0]~N !
~IREMEMBER~N: Although ~b~Ix[2][0]~N gives the ~Ivalue~N of element ~b~Ix[2][0]~N,
~b~Ix[2]~N gives the ~Iaddress~N of ~b~Ix[2][0]~N!!
Since ~b~Ix[2]~N is a ~r~Ipointer~N to ~b~Ix[2][0]~N, then ~Iaddress arithmetic~N
can be used to obtain the ~Iaddress~N of any element in the 1-dimensional
ARRAY ~b~Ix[2]~N.
That means that we could identify the element ~b~Ix[i][j]~N
by pointing just ~Ij~N elements past the address of ~b~Ix[i][0]~N.
That means that ~b~Ix[i]+j~N is a ~r~Ipointer~N to ~b~Ix[i][j]~N
That means that the 'value' of this element is ~b~I*(x[i]+j)~N.
~IREMEMBER~N: If x[i]+j is a pointer, then *(x[i]+j) is what it points to!
.b4-7
.b18-20
.WK8,32
MAMMA MIA!
.R23C1
~Iand that means that *(x[2]+3) and x[2][3] are EQUIVALENT~N
.b22-24
.WNT
What's in a name ? (of an ARRAY)
.R6C1
~V ~N
~V The name of a 1-dimensional ARRAY is a ~N
~V POINTER to the first element of the ARRAY! ~N
~V ~N
.b5-10
SO, if ~b~Ix~N is an ARRAY, declared as ~b~Iint x[10]~N, then ~b~Ix~N
is a ~r~Ipointer~N to ~b~Ix[0]~N (since ~b~Ix~N is 1-dimensional).
AND, if ~b~Ix~N is an ARRAY, declared as ~b~Iint x[10][15]~N, then ~b~Ix[7]~N
is a ~r~Ipointer~N to ~b~Ix[7][0]~N (since ~b~Ix[7]~N is 1-dimensional).
.K19,32
sounds OK!
.WN
.R10C1
...and finally, we may ~b~Iprintf("%d",x[7][2]); ~N to print the value of
the element, OR we may ~b~Iprintf("%d",*(x[7]+2));~N.
.b8-14
.K19,32
beautiful!
.WN
.T
That's all folks!
.K16,32
au revoir!
.q